#include <iostream>

#define CPP 0
#define TEST 1


//完美转发
//完美转发需要万能引用
//使用万能引用，所有实参的信息都会传递到万能引用中去，从而让编译器推导出来的函数模板的最终类型
 
namespace template_study{

    void func(int v1,int &v2){
        ++v2;//自增v2
        std::cout<<"被调函数"<<v2<<std::endl;
    }

    template<typename F,typename T1,typename T2>
    void funcMiddle_Temp(F f,T1&& t1,T2&& t2)   //f是一个函数指针void(*)(int,int)
    {
       // f(t1,t2);//经过转发之后，t1传递的是右值，经过转发函数之后，会变成左值，这样原始函数要接受右值的形参，就会报错
        //t2是左值，经过转发，还是左值
        std::forward<T1>(t1);  //T1 int
        std::forward<T2>(t2);  //T2 int&



    }


}
//完美转发就是让模板可以接受任意类型的参数
//并将其转发到目标函数
//目标函数会接受到转发函数接受到完全相同的参数，包括类型
//要实现完美转发，就要用到std::forward



//std::froward  为转发而存在的函数，要么返回一个左值，要么是一个右值
//万能引用才是foreward发挥作用的条件

//实参如果是一个左值，到了形参中还是左值(t2),forward能够转化成原来该实参的左值或者右值
//实参原来是个右值，到了形参中，会变成一个左值t1，forward能够转化回原来的左值性或者右值性，forward有将已经转变特性的阿函数还原的功能

//所以forward只对原来是个右值的情况有用
//注意：std::move()能够将一个左值转化成右值

#if TEST

int main(){


    using namespace template_study;
    int j=1,i=2;
    void (*p)(int,int&)=func;

    funcMiddle_Temp(p,j,i);


    return 0;
} 

#endif